import React from 'react';
import PropTypes from 'prop-types';
import cn from 'classnames';
import pathOr from 'ramda/es/pathOr';
import { gql, useMutation, useQuery } from '@apollo/client';
import { withRouter } from 'react-router';
import { Link } from 'react-router-dom';

import Button from '@kuiper-components/button';
import PageTable, { searchStringBuilder } from '@kuiper-components/page-table';
import notification from '@kuiper-components/notification';

import s from './strategy.module.css';
import Label from '../../../../components/Label';
import HostSearchInput from '../../../../components/HostSearchInput';
import confirm from '../../../../components/confirm';
import Edit from './Edit';

const TARGET_NOTE_GQL = gql`
	query TargetNoteList {
		JobMany(
			limit: 0
			filter: {
				cydEnabled: true
				verification: { isVerified: true }
				_operators: { target: { port: { in: [null, 80, 443] } } }
			}
		) {
			_id
			targetUrl
			note
		}
	}
`;

const BLACKLIST_STRATEGY_REMOVE_GQL = gql`
	mutation YunAQBlacklistStrategyRemoveOne($input: [String]!) {
		YunAQBlacklistStrategyRemoveOne(input: $input)
			@rest(
				type: "YunaqBlacklistStrategyRemoveOneResponse"
				path: "/cloud/udb_del_blacklist_set"
				method: "POST"
				endpoint: "v2"
			) {
			code
			msg
		}
	}
`;

const BLACKLIST_STRATEGY_UPDATE_GQL = gql`
	mutation YunAQBlacklistStrategyUpdateOne($input: [String]!) {
		YunAQBlacklistStrategyUpdateOne(input: $input)
			@rest(
				type: "YunaqBlacklistStrategyUpdateOneResponse"
				path: "/cloud/udb_edit_blacklist_set"
				method: "POST"
				endpoint: "v2"
			) {
			code
			msg
		}
	}
`;

function queryGQLBuilder() {
	return gql`
		query YunAQBlacklistStrategy(
			$searchKey: String = ""
			$page: Int = 1
			$limit: Int = 10
		) {
			dataPgination(searchKey: $searchKey, page: $page, limit: $limit)
				@rest(
					type: "YunaqBlacklistStrategyResponse"
					path: "/cloud/udb_get_blacklist_set?{args}"
					endpoint: "v2"
				) {
				code
				msg
				results {
					count
					data {
						_id
						is_alert
						used
						note
						targetUrl
						notification
						alertGroupIds
						settings {
							securityEvent {
								foreign_links
								black_links
								broken_links
								cryjack
								malscan
							}
							vul {
								critical
								high
								low
								medium
							}
						}
					}
				}
			}
		}
	`;
}

const queryVariablesBuilder = ({ filter, page, perPage }) => ({
	page,
	limit: perPage,
	searchKey: filter?.searchKey,
});
const getTotal = pathOr(1, ['dataPgination', 'results', 'count']);
const getTableRows = pathOr([], ['dataPgination', 'results', 'data']);
const getTablePageInfo = ({ tableData, variables }) => ({
	currentPage: variables.page,
	perPage: variables.perPage,
	pageCount: Math.ceil(getTotal(tableData) / variables.perPage),
});

function Strategy({ className, location, history }) {
	const { data: targetNote } = useQuery(TARGET_NOTE_GQL);
	const targetNoteList = targetNote?.JobMany || [];

	const [selectedRows, setSelectedRows] = React.useState({});
	const handleRowSelectionChange = rows => setSelectedRows(rows);
	const [refetch, setRefetch] = React.useState(null);
	const [remove] = useMutation(BLACKLIST_STRATEGY_REMOVE_GQL);
	const handleRemove = (ids, isUsed) =>
		confirm.warning({
			message: isUsed
				? '您确定要删除该资产风险应急响应策略？该资产还存在生效URL黑名单，如需删除，请前往“生效URL黑名单”操作。'
				: '您确定要删除该资产风险应急响应策略？',
			okText: '确定',
			cancelText: '取消',
			title: '提示',
			onOk: () =>
				remove({
					variables: {
						input: { settingIds: ids },
					},
				})
					.then(({ data }) => {
						const resp = data?.YunAQBlacklistStrategyRemoveOne || {};
						if (resp.code !== 200) {
							throw new Error(resp.msg);
						}
					})
					.then(() => {
						setSelectedRows({});
						refetch && refetch();
					})
					.catch(error => {
						notification.error({
							message: `删除失败`,
							description: error.message,
							placement: 'top',
						});
					}),
		});

	const [update] = useMutation(BLACKLIST_STRATEGY_UPDATE_GQL);
	const handlecreateOrUpdate = payload =>
		update({
			variables: { input: payload },
		})
			.then(({ data }) => {
				const resp = data?.YunAQBlacklistStrategyUpdateOne || {};
				if (resp.code !== 200) {
					throw new Error(resp.msg);
				}
			})
			.then(() => refetch && refetch())
			.catch(error => {
				notification.error({
					message: `更新失败`,
					description: error.message,
					placement: 'top',
				});
			});

	const search = new URLSearchParams(location.search);
	const filter = JSON.parse(
		decodeURIComponent(search.get('filter') || '') || '{}'
	);
	const handleSearch = searchKey => {
		const search = searchStringBuilder(location.search, {
			filter: JSON.stringify({ searchKey }),
			page: 1,
		});
		history.replace(`/yfld/blacklist/strategy?${search}`);
	};

	const [showCreateDialog, setShowCreateDialog] = React.useState(
		location.search.indexOf('create') > 0
	);
	React.useMemo(() => {
		if (location.search.indexOf('create') > 0) {
			setShowCreateDialog(true);
		}
	}, [location.pathname]);

	const columns = React.useMemo(
		() => [
			{
				title: '资产名称',
				dataIndex: 'note',
				key: 'note',
				// eslint-disable-next-line react/display-name
				render: note => (
					<Link
						to={`/yfld/blacklist/url?${new URLSearchParams({
							filter: JSON.stringify({ searchKey: note }),
						})}`}
					>
						{note}
					</Link>
				),
			},
			{
				title: '资产地址',
				dataIndex: 'targetUrl',
				key: 'targetUrl',
			},
			{
				title: '操作',
				dataIndex: '_id',
				key: '__actions__',
				width: 176,
				// eslint-disable-next-line react/display-name
				render: (_id, record) => {
					const target = targetNoteList.find(
						({ note, targetUrl }) =>
							record.targetUrl === targetUrl && record.note === note
					);
					return (
						<div className={s.actions}>
							<Edit
								primary
								jobIdSelectDisabled
								key={_id + JSON.stringify(record)}
								className={s.btn}
								value={{ ...record, job_id: target?._id }}
								onSubmit={handlecreateOrUpdate}
							>
								<Button link primary>
									编辑
								</Button>
							</Edit>
							<Button
								link
								primary
								className={s.btn}
								onClick={() => handleRemove([_id], record.used)}
							>
								删除
							</Button>
						</div>
					);
				},
			},
		],
		[targetNoteList, refetch]
	);

	return (
		<div className={cn(className, s.strategy)}>
			<Label note="ScanV将按照您设置的策略条件自动在知道创宇云防御平台加黑风险URL。">
				策略设置
			</Label>
			<div className={s.toolbox}>
				<Edit
					primary
					className={s.addBtn}
					visible={showCreateDialog}
					onChange={setShowCreateDialog}
					onSubmit={handlecreateOrUpdate}
				>
					<Button primary>添加策略</Button>
				</Edit>
				<HostSearchInput
					placeholder="请输入搜索内容"
					value={filter.searchKey}
					onChange={handleSearch}
				/>
			</div>
			<PageTable
				className={s.pageTable}
				routePrefix="/yfld/blacklist/strategy"
				rowSelected={selectedRows}
				onRowSelectionChange={handleRowSelectionChange}
				columns={columns}
				getRefetch={x => refetch || setRefetch(() => x)}
				queryGQLBuilder={queryGQLBuilder}
				queryVariablesBuilder={queryVariablesBuilder}
				getTotal={getTotal}
				getTableRows={getTableRows}
				getTablePageInfo={getTablePageInfo}
				rightBottomContent={
					<Button
						link
						primary
						disabled={Object.keys(selectedRows).length <= 0}
						onClick={() =>
							handleRemove(
								Object.entries(selectedRows).reduce((arr, [id, selected]) => {
									if (selected) arr.push(id);
									return arr;
								}, [])
							)
						}
					>
						批量删除
					</Button>
				}
			/>
		</div>
	);
}

Strategy.propTypes = {
	className: PropTypes.string,
	location: PropTypes.shape({
		pathname: PropTypes.string.isRequired,
		search: PropTypes.string,
	}).isRequired,
	history: PropTypes.shape({
		replace: PropTypes.func,
	}).isRequired,
};

Strategy.defaultProps = {
	className: s.url,
};

export default withRouter(Strategy);
